package com.zhengbing.tj.common;

import com.zhengbing.tj.entity.AuditLog;
import com.zhengbing.tj.entity.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;

import java.util.*;

/**
 * 审计日志工具类
 * 提供创建审计日志、比较实体变更等功能
 *
 * @author zhengbing
 * @date 2024-08-22
 */
public class AuditLogUtil {

    private static final Logger logger = LoggerFactory.getLogger(AuditLogUtil.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();

    // 操作类型常量
    public static final String OPERATION_TYPE_INSERT = "insert";
    public static final String OPERATION_TYPE_UPDATE = "update";
    public static final String OPERATION_TYPE_DELETE = "delete";

    /**
     * 创建审计日志对象
     *
     * @param entityType 实体类型
     * @param entityId 实体ID
     * @param operationType 操作类型
     * @param beforeData 操作前数据
     * @param afterData 操作后数据
     * @return 审计日志对象
     */
    public static AuditLog createAuditLog(String entityType, Long entityId, String operationType,
                                          Object beforeData, Object afterData) {
        AuditLog log = new AuditLog();
        Date now = new Date();
        
        // 设置基本信息
        log.setId(IdGenerator.nextId());
        log.setEntityType(entityType);
        log.setEntityName(entityType);  // 同时设置entityName，避免NOT NULL约束错误
        log.setEntityId(entityId);
        log.setOperationType(operationType);
        log.setCreateTime(now);
        log.setUpdateTime(now);
        
        // 设置操作用户信息
        User user = UserContext.getUser();
        if (user != null) {
            log.setOperatorId(user.getId());
            log.setOperatorName(user.getName());
            // 尝试从RequestContextUtil获取IP地址
            try {
                HttpServletRequest request = RequestContextUtil.getRequest();
                if (request != null) {
                    log.setOperatorIp(RequestContextUtil.getClientIp(request));
                }
            } catch (Exception e) {
                logger.error("Failed to get IP address: {}", e.getMessage(), e);
            }
        }
        
        // 设置变更详情
        if (beforeData != null || afterData != null) {
            try {
                if (beforeData instanceof Map && afterData == null) {
                    // 不记录变更详情，只记录基本信息
                    log.setChangeDetails(objectMapper.writeValueAsString(beforeData));
                } else {
                    // 记录变更详情
                    String beforeJson = beforeData != null ? objectMapper.writeValueAsString(beforeData) : null;
                    String afterJson = afterData != null ? objectMapper.writeValueAsString(afterData) : null;
                    
                    // 创建变更详情Map
                    Map<String, String> changeDetail = new HashMap<>();
                    changeDetail.put("before", beforeJson);
                    changeDetail.put("after", afterJson);
                    
                    // 转换为JSON字符串
                    log.setChangeDetails(objectMapper.writeValueAsString(changeDetail));   
                }
            } catch (Exception e) {
                logger.error("Failed to convert data to JSON: {}", e.getMessage(), e);
                log.setChangeDetails("Failed to record change detail: " + e.getMessage());
            }
        }
        
        return log;
    }
    
    /**
     * 比较两个对象的属性差异
     *
     * @param before 操作前对象
     * @param after 操作后对象
     * @return 属性差异Map
     */
    public static Map<String, Object[]> compareObjects(Object before, Object after) {
        if (before == null || after == null) {
            return new HashMap<>();
        }
        
        if (!before.getClass().equals(after.getClass())) {
            logger.warn("Cannot compare objects of different classes");
            return new HashMap<>();
        }
        
        Map<String, Object[]> diffMap = new HashMap<>();
        try {
            // 获取所有字段并比较
            // 这里可以根据需要实现更复杂的属性比较逻辑
            // 目前简化处理
            
            // 转换为Map进行比较
            Map<String, Object> beforeMap = objectMapper.convertValue(before, Map.class);
            Map<String, Object> afterMap = objectMapper.convertValue(after, Map.class);
            
            // 比较所有字段
            Set<String> allFields = new HashSet<>();
            allFields.addAll(beforeMap.keySet());
            allFields.addAll(afterMap.keySet());
            
            for (String field : allFields) {
                Object beforeValue = beforeMap.get(field);
                Object afterValue = afterMap.get(field);
                
                // 如果值不相同，记录变更
                if (!Objects.equals(beforeValue, afterValue)) {
                    diffMap.put(field, new Object[]{beforeValue, afterValue});
                }
            }
        } catch (Exception e) {
            logger.error("Failed to compare objects: {}", e.getMessage(), e);
        }
        
        return diffMap;
    }
    
    /**
     * 获取操作类型的中文描述
     *
     * @param operationType 操作类型
     * @return 中文描述
     */
    public static String getOperationTypeDesc(String operationType) {
        switch (operationType) {
            case OPERATION_TYPE_INSERT:
                return "新增";
            case OPERATION_TYPE_UPDATE:
                return "更新";
            case OPERATION_TYPE_DELETE:
                return "删除";
            default:
                return operationType;
        }
    }
}